package ad_exercise_2.model;

/**
 * 
 * Dit is een list-implementatie van het Stationnetwerk. Deze list-implementatie is veel meer objectgeorienteerd dan de matrix-implementatie.
 * Daarvoor maakt deze klasse gebruik van de objecten Station en Verbinding.
 * 
 * @author Karen Berntsen (s0815799)
 * @author Erik Stens (s0615374)
 */
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;

/**
 * 
 * 
 * @author Karen Berntsen (s0815799)
 * @author Erik Stens (s0615374)
 */
public class StationNetwerk_list extends StationNetwerk {
	HashSet<Verbinding>	verbindingSet	= new HashSet<Verbinding>();
	ArrayList<Station>	stationList		= new ArrayList<Station>();
	
	public StationNetwerk_list() {
		super();
	}
	
	public StationNetwerk_list(String filename) {
		super(filename);
	}
	
	@Override
	public void init(int numStations) {
		super.init(numStations);
		
		stationList.ensureCapacity(numStations);
	}
	
	@Override
	public void addVerbinding(int stationIndex1, int stationIndex2, int afstand) {
		Station station1 = addAndReturnStation(stationIndex1);
		Station station2 = addAndReturnStation(stationIndex2);
		
		Verbinding newVerbinding = new Verbinding(station1, station2, afstand);
		
		if (verbindingSet.add(newVerbinding)) {
			station1.addVerbinding(newVerbinding);
			station2.addVerbinding(newVerbinding);
		}
	}
	
	public void removeStation(Station station) {
		stationList.remove(station);
		for (Verbinding verb : verbindingSet) {
			if (verb.contains(station)) {
				verbindingSet.remove(verb);
			}
		}
		
	}
	
	public void addStation(Station station) {
		int stationIndex = station.getIndex();
		Station station1 = stationList.get(station.getIndex());
		if (station1 == null) {
			stationList.set(stationIndex, station);
		}
	}
	
	public void addStation(int stationIndex) {
		Station station;
		if (!stationList.isEmpty()) {
			station = stationList.get(stationIndex);
			if (station == null) {
				stationList.set(stationIndex, station = new Station(stationIndex));
			}
		} else {
			stationList.set(stationIndex, station = new Station(stationIndex));
		}
	}
	
	public Station addAndReturnStation(int stationIndex) {
		Station station;
		if (!stationList.isEmpty()) {
			station = stationList.get(stationIndex);
			if (station == null) {
				stationList.set(stationIndex, station = new Station(stationIndex));
			}
		} else {
			station = new Station(stationIndex);
			stationList.set(stationIndex, station);
		}
		return station;
	}
	
	@Override
	public void kortsteRoute(int beginStationIndex, int eindStationIndex) {
		Station beginStation = stationList.get(beginStationIndex);
		Station eindStation = stationList.get(eindStationIndex);
		beginStation.setColour(true);
		Station lastColoured = beginStation;
		int routeAfstand = 0;
		while (!eindStation.getColour()) {
			Iterator<Verbinding> itr = lastColoured.getVerbindingSet().iterator();
			while (itr.hasNext()) {
				Verbinding verb = itr.next();
				Station otherStation = verb.getOtherStation(lastColoured);
				if (verb.getAfstand() + routeAfstand < otherStation.getDistanceToStart()) {
					otherStation.setDistanceToStart(verb.getAfstand() + routeAfstand);
					otherStation.setVorigStation(lastColoured);
				}
			}
			int minimum = INF;
			Station station2Colour = lastColoured;
			Iterator<Station> StatItr = stationList.iterator();
			while (itr.hasNext()) {
				Station stat = StatItr.next();
				if (!stat.getColour() && stat.getDistanceToStart() < minimum) {
					minimum = stat.getDistanceToStart();
					station2Colour = stat;
				}
			}
			lastColoured = station2Colour;
			station2Colour.setColour(true);
			routeAfstand = minimum;
		}
		System.out.print("min afstand = ");
		System.out.println(routeAfstand);
		ArrayList<Station> finalRoute = getRoute(beginStation, eindStation);
		printRoute(finalRoute);
	}
	
	public void printRoute(ArrayList<Station> finalRoute) {
		System.out.println("The shortest route is:");
		for (Station station : finalRoute) {
			System.out.print(station.getName());
			System.out.print(",");
		}
	}
	
	public ArrayList<Station> getRoute(Station beginStation, Station eindStation) {
		ArrayList<Station> finalRoute = new ArrayList<Station>();
		finalRoute = getRoute(beginStation, eindStation, finalRoute);
		return finalRoute;
	}
	
	public ArrayList<Station> getRoute(Station beginStation, Station eindStation, ArrayList<Station> finalRoute) {
		if (finalRoute.isEmpty()) {
			finalRoute.add(eindStation);
		}
		eindStation = eindStation.getVorigStation();
		if (!beginStation.equals(eindStation)) {
			finalRoute.add(0, eindStation);
			finalRoute = getRoute(beginStation, eindStation, finalRoute);
		} else {
			finalRoute.add(0, beginStation);
		}
		return finalRoute;
	}
}
